home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / network / ka9q / nhclb120.zoo / slip.c < prev    next >
C/C++ Source or Header  |  1992-06-18  |  9KB  |  465 lines

  1. /* Send and receive IP datagrams on serial lines. Compatible with SLIP
  2.  * under Berkeley Unix.
  3.  */
  4. #include <stdio.h>
  5. #include "config.h"
  6. #include "global.h"
  7. #include "mbuf.h"
  8. #include "netuser.h"
  9. #include "timer.h"
  10. #include "iface.h"
  11. #include "ax25.h"
  12. #include "ip.h"
  13. #include "tcp.h"
  14. #include "slhc.h"
  15. #include "slip.h"
  16. #include "asy.h"
  17. #include "trace.h"
  18. #ifndef MWC
  19. #if defined(MODEM_CALL)
  20. #include <string.h>
  21. #endif
  22. #endif
  23.  
  24. static struct mbuf *slip_encode(); 
  25. static void asy_start();
  26. static int slipq();
  27. extern unsigned restricted_dev;
  28. int asy_ioctl();
  29. int kiss_ioctl();
  30. int slip_send();
  31. void doslip();
  32. int asy_output();
  33.  
  34. /* Slip level control structure */
  35. struct slip slip[ASY_MAX];
  36. void slip_recv();
  37.  
  38. /* Send routine for point-to-point slip
  39.  * This is a trivial function since there is no slip link-level header
  40.  */
  41. /*ARGSUSED*/
  42. int
  43. slip_send(data,interface,gateway,precedence,delay,throughput,reliability)
  44. struct mbuf *data;        /* Buffer to send */
  45. struct interface *interface;    /* Pointer to interface control block */
  46. int32 gateway;            /* Ignored (SLIP is point-to-point) */
  47. char precedence;
  48. char delay;
  49. char throughput;
  50. char reliability;
  51. {
  52.     register struct slip *sp;
  53.     int type;
  54.  
  55.     if(interface == NULLIF){
  56.         free_p(data);
  57.         return -1;
  58.     }
  59.     dump(interface,IF_TRACE_OUT,TRACE_IP,data);
  60.     sp = &slip[interface->dev];
  61.     if (sp->vjcomp) {
  62.         /* Attempt IP/ICP header compression */
  63.         type = slhc_compress((struct slcompress *)sp->slcomp,&data,1);
  64.         data->data[0] |= type;
  65.     }
  66.     return (*interface->raw)(interface,data);
  67. }
  68. /* Send a raw slip frame -- also trivial */
  69. int
  70. slip_raw(interface,data)
  71. struct interface *interface;
  72. struct mbuf *data;
  73. {
  74.     /* Queue a frame on the slip output queue and start transmitter */
  75.     return slipq(interface->dev,data);
  76. }
  77. /* Encode a raw packet in slip framing, put on link output queue, and kick
  78.  * transmitter
  79.  */
  80. static int
  81. slipq(dev,data)
  82. int16 dev;        /* Serial line number */
  83. struct mbuf *data;    /* Buffer to be sent */
  84. {
  85.     register struct slip *sp;
  86.     struct mbuf *slip_encode(),*bp;
  87.     void asy_start();
  88.  
  89.     if((bp = slip_encode(data)) == NULLBUF)
  90.         return -1;    
  91.  
  92.     sp = &slip[dev];
  93.     enqueue(&sp->sndq,bp);
  94.     sp->sndcnt++;
  95.     if(sp->tbp == NULLBUF)
  96.         asy_start(dev);
  97.     return 0;
  98. }
  99. /* Start output, if possible, on asynch device dev */
  100. static void
  101. asy_start(dev)
  102. int16 dev;
  103. {
  104.     register struct slip *sp;
  105.  
  106.     if(!stxrdy(dev))
  107.         return;        /* Transmitter not ready */
  108.  
  109.     sp = &slip[dev];
  110.     if(sp->tbp != NULLBUF){
  111.         /* transmission just completed */
  112.         free_p(sp->tbp);
  113.         sp->tbp = NULLBUF;
  114.     }
  115.     if(sp->sndq == NULLBUF)
  116.         return;    /* No work */
  117.  
  118.     sp->tbp = dequeue(&sp->sndq);
  119.     sp->sndcnt--;
  120.     asy_output(dev,sp->tbp->data,sp->tbp->cnt);
  121. }
  122. /* Encode a packet in SLIP format */
  123. static
  124. struct mbuf *
  125. slip_encode(bp)
  126. struct mbuf *bp;
  127. {
  128.     struct mbuf *lbp;    /* Mbuf containing line-ready packet */
  129.     register char *cp;
  130.     char c;
  131.  
  132.     /* Allocate output mbuf that's twice as long as the packet.
  133.      * This is a worst-case guess (consider a packet full of FR_ENDs!)
  134.      */
  135.     lbp = alloc_mbuf(2*len_mbuf(bp) + 2);
  136.     if(lbp == NULLBUF){
  137.         /* No space; drop */
  138.         free_p(bp);
  139.         return NULLBUF;
  140.     }
  141.     cp = lbp->data;
  142.  
  143.     /* Flush out any line garbage */
  144.     *cp++ = FR_END;
  145.  
  146.     /* Copy input to output, escaping special characters */
  147.     while(pullup(&bp,&c,1) == 1){
  148.         switch(uchar(c)){
  149.         case FR_ESC:
  150.             *cp++ = FR_ESC;
  151.             *cp++ = T_FR_ESC;
  152.             break;
  153.         case FR_END:
  154.             *cp++ = FR_ESC;
  155.             *cp++ = T_FR_END;
  156.             break;
  157.         default:
  158.             *cp++ = c;
  159.         }
  160.     }
  161.     *cp++ = FR_END;
  162.     lbp->cnt = cp - lbp->data;
  163.     return lbp;
  164. }
  165. /* Process incoming bytes in SLIP format
  166.  * When a buffer is complete, return it; otherwise NULLBUF
  167.  */
  168. static
  169. struct mbuf *
  170. slip_decode(dev,c)
  171. int16 dev;    /* Slip unit number */
  172. char c;        /* Incoming character */
  173. {
  174.     struct mbuf *bp;
  175.     register struct slip *sp;
  176.  
  177.     sp = &slip[dev];
  178.     switch(uchar(c)){
  179.     case FR_END:
  180.         bp = sp->rbp;
  181.         sp->rbp = NULLBUF;
  182.         sp->rcnt = 0;
  183.         return bp;    /* Will be NULLBUF if empty frame */
  184.     case FR_ESC:
  185.         sp->escaped = 1;
  186.         return NULLBUF;
  187.     }
  188.     if(sp->escaped){
  189.         /* Translate 2-char escape sequence back to original char */
  190.         sp->escaped = 0;
  191.         switch(uchar(c)){
  192.         case T_FR_ESC:
  193.             c = FR_ESC;
  194.             break;
  195.         case T_FR_END:
  196.             c = FR_END;
  197.             break;
  198.         default:
  199.             sp->errors++;
  200.             break;
  201.         }
  202.     }
  203.     /* We reach here with a character for the buffer;
  204.      * make sure there's space for it
  205.      */
  206.     if(sp->rbp == NULLBUF){
  207.         /* Allocate first mbuf for new packet */
  208.         if((sp->rbp1 = sp->rbp = alloc_mbuf(SLIP_ALLOC)) == NULLBUF)
  209.             return NULLBUF; /* No memory, drop */
  210.         sp->rcp = sp->rbp->data;
  211.     } else if(sp->rbp1->cnt == SLIP_ALLOC){
  212.         /* Current mbuf is full; link in another */
  213.         if((sp->rbp1->next = alloc_mbuf(SLIP_ALLOC)) == NULLBUF){
  214.             /* No memory, drop whole thing */
  215.             free_p(sp->rbp);
  216.             sp->rbp = NULLBUF;
  217.             sp->rcnt = 0;
  218.             return NULLBUF;
  219.         }
  220.         sp->rbp1 = sp->rbp1->next;
  221.         sp->rcp = sp->rbp1->data;
  222.     }
  223.     /* Store the character, increment fragment and total
  224.      * byte counts
  225.      */
  226.     *sp->rcp++ = c;
  227.     sp->rbp1->cnt++;
  228.     sp->rcnt++;
  229.     return NULLBUF;
  230. }
  231. /* Process SLIP line I/O */
  232. void
  233. doslip(interface)
  234. struct interface *interface;
  235. {
  236.     char c;
  237.     struct mbuf *bp;
  238.     int16 dev;
  239.     int16 asy_recv();
  240.     struct slip *sp;
  241.  
  242.     dev = interface->dev;
  243.     if(dev == restricted_dev) return;
  244.     sp = &slip[dev];
  245.  
  246.     /* Process any pending input */
  247.     while(asy_recv(dev,&c,1) != 0) {
  248.         if((bp = slip_decode(dev,c)) == NULLBUF)
  249.             continue;
  250.  
  251. /*
  252.         if (sp->iface->trace & IF_TRACE_RAW)
  253.             raw_dump(sp->iface,IF_TRACE_IN,bp);
  254. */
  255.         if (sp->vjcomp) {
  256.             if ((c = bp->data[0]) & SL_TYPE_COMPRESSED_TCP) {
  257.                 if ( slhc_uncompress((struct slcompress *)sp->slcomp, &bp) <= 0 ) {
  258.                     free_p(bp);
  259.                     sp->errors++;
  260.                     continue;
  261.                 }
  262.             } else if (c >= SL_TYPE_UNCOMPRESSED_TCP) {
  263.                 bp->data[0] &= 0x4f;
  264.                 if ( slhc_remember((struct slcompress *)sp->slcomp, &bp) <= 0 ) {
  265.                     free_p(bp);
  266.                     sp->errors++;
  267.                     continue;
  268.                 }
  269.             }
  270.         }
  271.         (*slip[dev].recv)(interface,bp);
  272.     }
  273.     /* Kick the transmitter if it's idle */
  274.     if(stxrdy(dev))
  275.         asy_start(dev);
  276. }
  277. /* Unwrap incoming SLIP packets -- trivial operation since there's no
  278.  * link level header
  279.  */
  280. void
  281. slip_recv(interface,bp)
  282. struct interface *interface;
  283. struct mbuf *bp;
  284. {
  285.     int ip_route();
  286.  
  287.     /* By definition, all incoming packets are "addressed" to us */
  288.     dump(interface,IF_TRACE_IN,TRACE_IP,bp);
  289.     ip_route(bp,0);
  290. }
  291.  
  292. #if defined(MODEM_CALL)
  293.  
  294. void check_time(),keep_things_going();
  295.  
  296. static char *ex="r\015t\011s n\012E\004b\010\\\\N\000";
  297. static struct timer ar;
  298. static int debug;
  299.  
  300. static
  301. int m_send(dev, a)
  302. unsigned dev;
  303. char *a;
  304. {
  305.     unsigned l;
  306.     char *ss, *cp, *pt;
  307.  
  308.     ss=pt=a;
  309.     l=0;
  310.     while(*a) {
  311.         if(*a=='\\') {
  312.             a++;
  313.             if(*a=='d') {
  314.                 asy_output(dev,ss,l);
  315.                 l=0;
  316.                 a++;
  317.                 ss=pt=a;
  318.                 set_timer(&ar,1000);
  319.                 start_timer(&ar);
  320.                     while(ar.state == TIMER_RUN)
  321.                     keep_things_going();
  322.                 continue;
  323.             }
  324.             if((cp = strchr(ex,*a)) != NULL) {
  325.                 *pt++ = *(cp+1);
  326.                 l++;
  327.                 a++;
  328.                 continue;
  329.             }
  330.         } /* if(*a=='\\') */
  331.         *pt++ = *a++;
  332.         l++;
  333.     }
  334.     asy_output(dev,ss,l);
  335. } /* m_send */
  336.  
  337. /******************************************************************************
  338.  * returns the character position of the substring pat within the string
  339.  *  src if the substring exists, 0 if the substring does not exist.
  340.  *  the first character position is considered to be 1, not 0 which
  341.  *  is the first position within the array.
  342.  */
  343. static
  344. int xinstr(src,pat)
  345. char *src,*pat;
  346. {
  347.     register char *s_src, *s_pat;
  348.     int rtn;
  349.  
  350.     s_src=src;
  351.     s_pat=pat;
  352.     rtn=1;
  353.     while(*s_src) {
  354.         while((*s_pat) && (*s_src==*s_pat)) { s_src++; s_pat++; }
  355.         if(!(*s_pat)) return(rtn);
  356.         rtn++; s_pat=pat; s_src=(++src);
  357.     }
  358.     return(0);
  359. } /* xinstr */
  360.  
  361. static
  362. int m_expect(dev, a)
  363. unsigned dev;
  364. char *a;
  365. {
  366.     char *str, *pstr, c;
  367.     int tot;
  368.  
  369.     if(*a=='\\') return 1;
  370. /*
  371.  * make room for the received string
  372.  */
  373.         if((str=malloc(5000)) == NULL) {
  374.         printf("No room for malloc: m_expect\n");
  375.         fflush(stdout);
  376.         return -1;
  377.     }
  378. /*
  379.  * a single backspace means don't wait for anything
  380.  */
  381.     pstr=str;
  382.     *pstr='\0';
  383.     tot=0;
  384.     set_timer(&ar,30000);
  385.     start_timer(&ar);
  386.     while (!xinstr(str,a)) {
  387.         while(asy_recv(dev,&c,1)) { 
  388. /*
  389.  * ignore incoming nulls
  390.  */
  391.             if(c) {
  392.                 *(pstr++)=c;
  393.                 *pstr='\0';
  394.                 if(++tot > 4995) {
  395.                     if(debug) printf("%s",str);fflush(stdout);
  396.                     free(str);
  397.                     ret